package com.kx.game.center.utils;

import com.alibaba.fastjson.JSONObject;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.*;
import java.net.URLDecoder;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;


public class RSAEncrypt {

    //默认公钥(openssl)

    public static final String DEFAULT_PUBLIC_KEY =
            "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuOkEZLOYCcljisbNBMAg" + "\r\n" +
                    "y2a37OjvB9XURjQRtvbXK12HkLXWtrORqt9fk59+PRG7UGObLmVUnVDSGIN1IFGD" + "\r\n" +
                    "q0vLy5Y8/LKjmcBrp1vcXyD0RHqTfzc2JjQnqxLBsSGJZM4OV3HDd8B7I853bAoL" + "\r\n" +
                    "ZfMwrpWgS6rKkEPQt5nwOnPhHMFoGSqtsZ8mdeZRzjGYshrx0Qpw9SIUfmTf3zkk" + "\r\n" +
                    "Tu7ep1FjBrAm2j6BW11Ka2HYxlMf1Ne6RXrGUf+s+jDH5kXLeJlB/aLV/OHRoZaL" + "\r\n" +
                    "sBB2hLKOd8bRcwIdvKD0Aqt0ySHSxNp+CXDbu66gyXRtyFZXVlgveWPNpAMSCLg/" + "\r\n" +
                    "/wIDAQAB" + "\r\n";

    /**
     * 私钥
     */
    private RSAPrivateKey privateKey;

    /**
     * 公钥
     */
    private RSAPublicKey publicKey;

    /**
     * 字节数据转字符串专用集合
     */
    private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

    /**
     * 获取私钥
     *
     * @return 当前的私钥对象
     */
    public RSAPrivateKey getPrivateKey() {
        return privateKey;
    }

    /**
     * 获取公钥
     *
     * @return 当前的公钥对象
     */
    public RSAPublicKey getPublicKey() {
        return publicKey;
    }

    /**
     * 随机生成密钥对
     */
    public void genKeyPair() {
        KeyPairGenerator keyPairGen = null;
        try {
            keyPairGen = KeyPairGenerator.getInstance("RSA");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        keyPairGen.initialize(1024, new SecureRandom());
        KeyPair keyPair = keyPairGen.generateKeyPair();
        this.privateKey = (RSAPrivateKey) keyPair.getPrivate();
        this.publicKey = (RSAPublicKey) keyPair.getPublic();
    }

//    /**
//     * 从文件中输入流中加载公钥
//     *
//     * @param in 公钥输入流
//     * @throws Exception 加载公钥时产生的异常
//     */
//    public void loadPublicKey(InputStream in) throws Exception {
//        try {
//            BufferedReader br = new BufferedReader(new InputStreamReader(in));
//            String readLine = null;
//            StringBuilder sb = new StringBuilder();
//            while ((readLine = br.readLine()) != null) {
//                if (readLine.charAt(0) == '-') {
//                    continue;
//                } else {
//                    sb.append(readLine);
//                    sb.append('\r');
//                }
//            }
//            loadPublicKey(sb.toString());
//        } catch (IOException e) {
//            throw new Exception("公钥数据流读取错误");
//        } catch (NullPointerException e) {
//            throw new Exception("公钥输入流为空");
//        }
//    }


//    /**
//     * 从字符串中加载公钥
//     *
//     * @param publicKeyStr 公钥数据字符串
//     * @throws Exception 加载公钥时产生的异常
//     */
//    public void loadPublicKey(String publicKeyStr) throws Exception {
//        //System.out.println("publicKeyStr:"+ publicKeyStr);
//        try {
//            BASE64Decoder base64Decoder = new BASE64Decoder();
//            byte[] buffer = base64Decoder.decodeBuffer(publicKeyStr);
//            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
//            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
//            this.publicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);
//        } catch (NoSuchAlgorithmException e) {
//            throw new Exception("无此算法");
//        } catch (InvalidKeySpecException e) {
//            throw new Exception("公钥非法");
//        } catch (IOException e) {
//            throw new Exception("公钥数据内容读取错误");
//        } catch (NullPointerException e) {
//            throw new Exception("公钥数据为空");
//        }
//    }

    /**
     * 公钥加密过程
     *
     * @param publicKey     公钥
     * @param plainTextData 明文数据
     * @return
     * @throws Exception 加密过程中的异常信息
     */
    public byte[] encrypt(RSAPublicKey publicKey, byte[] plainTextData) throws Exception {
        if (publicKey == null) {
            throw new Exception("加密公钥为空, 请设置");
        }
        Cipher cipher = null;
        try {
            //使用默认RSA
            cipher = Cipher.getInstance("RSA");
            //cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());    
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] output = cipher.doFinal(plainTextData);
            return output;
        } catch (NoSuchAlgorithmException e) {
            throw new Exception("无此加密算法");
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
            return null;
        } catch (InvalidKeyException e) {
            throw new Exception("加密公钥非法,请检查");
        } catch (IllegalBlockSizeException e) {
            throw new Exception("明文长度非法");
        } catch (BadPaddingException e) {
            throw new Exception("明文数据已损坏");
        }
    }

    /**
     * 公钥解密过程
     *
     * @param publicKey  公钥
     * @param cipherData 密文数据
     * @return 明文
     * @throws Exception 解密过程中的异常信息
     */
    public byte[] decrypt(RSAPublicKey publicKey, byte[] cipherData) throws Exception {
        if (publicKey == null) {
            throw new Exception("解密公钥为空, 请设置");
        }
        Cipher cipher = null;
        try {
            //使用默认RSA
            cipher = Cipher.getInstance("RSA");
            //cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());  
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            byte[] output = cipher.doFinal(cipherData);
            return output;
        } catch (NoSuchAlgorithmException e) {
            throw new Exception("无此解密算法");
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
            return null;
        } catch (InvalidKeyException e) {
            throw new Exception("解密公钥非法,请检查");
        } catch (IllegalBlockSizeException e) {
            throw new Exception("密文长度非法");
        } catch (BadPaddingException e) {
            throw new Exception("密文数据已损坏");
        }
    }


    /**
     * 字节数据转十六进制字符串
     *
     * @param data 输入数据
     * @return 十六进制内容
     */
    public static String byteArrayToString(byte[] data) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < data.length; i++) {
            //取出字节的高四位 作为索引得到相应的十六进制标识符 注意无符号右移   
            stringBuilder.append(HEX_CHAR[(data[i] & 0xf0) >>> 4]);
            //取出字节的低四位 作为索引得到相应的十六进制标识符   
            stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]);
            if (i < data.length - 1) {
                stringBuilder.append(' ');
            }
        }
        return stringBuilder.toString();
    }

//    public static boolean checkSign(String public_key, String sign, String order_id, String account, String amount, String billno, int status) {
//        boolean result = false;
//        RSAEncrypt rsaEncrypt = new RSAEncrypt();
//        //rsaEncrypt.genKeyPair();
//
//        //加载公钥
//        try {
//            rsaEncrypt.loadPublicKey(public_key);
//        } catch (Exception e) {
//            e.printStackTrace();
//            return result;
//        }
//
//
//        try {
//            BASE64Decoder base64Decoder = new BASE64Decoder();
//            byte[] dcDataStr = base64Decoder.decodeBuffer(sign);
//            byte[] plainData = rsaEncrypt.decrypt(rsaEncrypt.getPublicKey(), dcDataStr);
//            JSONObject signJson = JSONObject.parseObject(new String(plainData, "utf-8"));
//            String signOrderId = signJson.getString("order_id");
//            String signAccount = signJson.getString("account");
//            String signAmount = signJson.getString("amount");
//            String signBillno = URLDecoder.decode(signJson.getString("billno"), "utf-8");
//            int signStatus = signJson.getInteger("status");
//            System.out.println("sign : " + sign + " order_id : " + order_id + " account : " + account + " amount" + amount + " billno" + billno + " status : " + status);
//            System.out.println("signOrderId : " + signOrderId + " signAccount : " + signAccount + " signAmount : " + signAmount + " signBillno" + signBillno + " signStatus:" + signStatus);
//            if (!signOrderId.equals(order_id) || !signAccount.equals(account) || !signAmount.equals(amount)
//                    || !signBillno.equals(billno) || signStatus != status) {
//                System.out.println("chechSign is false");
//                return false;
//            }
//
//        } catch (Exception e) {
//            e.printStackTrace();
//            return result;
//        }
//
//        System.out.println("chechSign is true");
//        return true;
//    }


//    public static void main(String[] args) throws UnsupportedEncodingException {
//        RSAEncrypt rsaEncrypt = new RSAEncrypt();
//        //rsaEncrypt.genKeyPair();
//
//        //加载公钥
//        try {
//            rsaEncrypt.loadPublicKey(RSAEncrypt.DEFAULT_PUBLIC_KEY);
//            System.out.println("加载公钥成功");
//        } catch (Exception e) {
//            System.err.println(e.getMessage());
//            System.err.println("加载公钥失败");
//        }
//
//        //文档测试数据
//        String testDataStr = "JfAyAp%2B3ZSFvC52fxT5HtPXkJJylE8XQM1hVMxpUjyc0PoZUK8e0RsaILks5KFvKGlpTcdTDFq4WqHOTk2qgl%2F7Jg3fM%2B8BxxyAOMShITVWOhtTlH4nSfZxADwr0o49Y982%2Bsa7ytIC1dasxnWpasDN0cbCIqBoIB1Q77u%2FzL9X1aPAC7xT%2Fz4x6hz5UlAtcksta4fl6U%2BhDbLO7VAGyU%2Fjh%2F0ZkcsyYQAXt8ku6EZXE6Rukgn5EnDxv6fzvTnhUN9RPJAozzfqdQB0g9Ow6tvjlbbBftwP3OTxcEWgKsaamYW74lBvIVhq%2BGIHdd6r%2BzAQGV%2FXSNG1FUd7m2DlGlQ%3D%3D";
//
//        testDataStr = URLDecoder.decode(testDataStr, "utf-8");
//
//        System.out.println("!!!!!!" + checkSign(RSAEncrypt.DEFAULT_PUBLIC_KEY, testDataStr, "2014061737383569", "Jxzq", "6.00", URLDecoder.decode("60%E9%87%91%E5%B8%81", "utf-8"), 0));
//
//        try {
//            BASE64Encoder base64Encoder = new BASE64Encoder();
//            BASE64Decoder base64Decoder = new BASE64Decoder();
//            byte[] dcDataStr = base64Decoder.decodeBuffer(testDataStr);
//            byte[] plainData = rsaEncrypt.decrypt(rsaEncrypt.getPublicKey(), dcDataStr);
//            System.out.println("文档测试数据明文长度:" + plainData.length);
//            System.out.println(RSAEncrypt.byteArrayToString(plainData));
//            System.out.println(new String(plainData, "utf-8"));
//            System.out.println(JSONObject.parseObject(new String(plainData, "utf-8")));
//
//        } catch (Exception e) {
//            System.err.println(e.getMessage());
//        }
//    }
}  